<template>
  <div class="port-wrapper">
    <Card>
      <Divider>在线检测域名或者ip的端口是否开放</Divider>
      <div class="port-box">
        <div class="port-item">
          <h4><span style="color: red;"> * </span>域名/ip</h4>
          <Input v-model="host" placeholder="请输入域名或者ip地址"></Input>
        </div>
        <div class="port-item">
          <h4><span style="color: red;"> * </span>端口号</h4>
          <Input v-model="textareaData" type="textarea" :autosize="{minRows: 3,maxRows: 5}"></Input>
          <p style="font-size: 12px;">多个以","隔开，支持范围书写，例如:1,2,3,10,20,6,100,105,33一次最多不能超过20个</p>
        </div>
        <div class="port-item" style="text-align: center;">
          <Button type="primary" @click="handlePortScan">端口扫描</Button>
        </div>
        <div class="port-item">
          <Table :columns="columns" :data="data"></Table>
        </div>
        <div class="port-item">
          <p>端口号的范围是从1～65535。其中1～1024是被RFC 3232规定好了的，被称作“众所周知的端口”(Well Known Ports)；从1025～65535的端口被称为动态端口（Dynamic Ports），可用来建立与其它主机的会话，也可由用户自定义用途。</p>
          <p>一些常见的端口号及其用途如下：</p>
          <p>1、21端口：FTP 文件传输服务</p>
          <p>2、22端口：SSH 端口</p>
          <p>3、80端口：HTTP 超文本传输服务</p>
          <p>4、443端口：HTTPS 加密的超文本传输服务</p>
          <p>5、3306端口：MySQL 默认端口号</p>
          <p>6、1521端口：Oracle数据库服务</p>
        </div>
      </div>
      <!-- 加载等待 -->
      <Spin fix v-show="show">
        <Icon type="ios-loading" size=18 class="demo-spin-icon-load"></Icon>
        <div>处理中...</div>
      </Spin>
    </Card>
  </div>
</template>

<script>
import NetMap from 'netmap.js'

export default {
  name: 'PortUtil',
  data(){
    return {
      netmap: null,
      host: 'baidu.com',
      textareaData:'21,22,80,443,3306',
      columns: [
        {
          title: '域名/ip',
          key: 'host'
        },
        {
          title: '端口',
          key: 'port'
        },
        {
          title: '端口状态',
          key: 'open',
          render: (h, params) => {
            return h('div', [
              h('Tag', {
                props: {
                  color: params.row.open ? 'success' : 'error'
                }
              }, params.row.open ? '开启' : '超时/关闭')
            ]);
          }
        },
        {
          title: '响应时间(ms)',
          key: 'delta'
        }
      ],
      data: [],
      show: false
    }
  },
  created(){
    this.netmap = new NetMap({
      protocol: 'http',
      timeout: 3000
    })
  },
  methods:{
    handlePortScan(){
      if(this.host.length <= 0){
        this.$Message.warning('请先输入域名或者ip！')
        return
      }
      if(this.host.indexOf('http://') != -1 || this.host.indexOf('https://') != -1){
        let tempData = this.host.split('/');
        this.host = tempData[2]
      }
      if(this.textareaData.length <= 0){
        this.$Message.warning('请先输入端口！')
        return
      }
      let ports = []
      try {
        ports = this.textareaData.split(',')
        if(ports.length <= 0){
          this.$Message.warning('请先输入端口！')
          return
        }
        let reg = new RegExp("^[0-9]*$")
        ports.forEach(item =>{
          if(!reg.test(item)){
            throw new Error('端口格式错误！')
          }
        })
        if(ports.length >= 20){
          this.$Message.warning('端口数量太多！')
          return
        }
      } catch (error) {
        console.log('error:',error.message)
        this.$Message.error(error.message)
        return
      }

      let hosts = []
      hosts.push(this.host)
      this.show = true
      this.data = []
      this.netmap.tcpScan(hosts, ports).then(res => {
        res.hosts[0].ports.forEach(item => {
          this.data.push({
            host: res.hosts[0].host,
            port: item.port,
            open: item.open,
            delta: item.delta
          })
        })
        this.show = false
      })
    }
  }
}
</script>

<style lang="less" scoped>
.port-wrapper{
  max-width: 1280px;
  margin: 0 auto;
  padding: 10px;
  .port-box{
    max-width: 600px;
    min-height: ~"calc(100vh - 259px)";
    margin: 0 auto;
    .port-item{
      margin-top: 20px;
    }
  }
  .demo-spin-icon-load{
    animation: ani-demo-spin 1s linear infinite;
  }
}
</style>

<style scoped>
.port-item >>> textarea.ivu-input{
  resize: none;
}
</style>
